<template>
  <div style="width: 100%">
    <div v-loading="loading" id="markerContainer" style="height: 760px"></div>

    <el-dialog :visible.sync="showDialog" width="30%">
      <img :src="bigImg" style="width: 100%" alt=""/>
    </el-dialog>
  </div>
</template>

<script>
import AMapLoader from '@amap/amap-jsapi-loader'
import {securityJsCode, key} from './mapConfig'
import MapBlue from '@/assets/dashboard/breath_blue.png'
import MapGreen from '@/assets/dashboard/breath_green.png'
import MapRed from '@/assets/dashboard/breath_red.png'
import UavImage from '@/assets/uav.png'

window._AMapSecurityConfig = {securityJsCode}
let AMap = null

export default {
  props: {
    data: {
      type: Array,
      default: () => []
    },
    center: {
      type: Array,
      default: () => [114.04038, 22.676254]
    },
    icon: {
      type: Number,
      default: 2
    },
    infoWindowIndex: {
      type: Number,
      default: -1
    }
  },
  data() {
    return {
      showDialog: false,
      bigImg: '',
      map: null,
      loading: false,
      infoWindow: null,
      markerList: [],
      iconMap: [MapRed, MapGreen, MapBlue],
      AMap: null,
      mapLoca: null,
      markerClusterer: null,
      uav: {},
      uavPassed: {}
    }
  },
  watch: {
    data() {
      const interval = setInterval(() => {
        if (!this.loading && this.map) {
          this.setMarker()
          clearInterval(interval)
        }
      }, 100)
    },
    icon(val) {
      for (let i in this.markerList) {
        if (this.markerList[i].getExtData() === 'newMarker') {
          this.markerList[i].setIcon(new AMap.Icon({
            size: new AMap.Size(24, 24),
            imageSize: new AMap.Size(24, 24),
            image: this.iconMap[val - 1]
          }))
        }
      }
    }
  },
  mounted() {
    this.initMap()
  },
  methods: {
    async initMap() {
      try {
        this.loading = true

        AMap = await AMapLoader.load({
          key,
          version: '2.0',
          plugins: ['AMap.DistrictSearch', 'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.MoveAnimation'],
          Loca: {
            version: '2.0.0'
          },
        })
        this.AMap = AMap

        const param = {
          resizeEnable: true,
          // layers: [new AMap.TileLayer.Satellite(), new AMap.TileLayer.RoadNet()],
          zoom: 14, // 初始化地图可视级别
          minZoom: 10, // 地图可视最小级别
          maxZoom: 24, // 地图可视最大级别
          mapStyle: "amap://styles/darkblue", //设置地图的显示样式
        }
        if (!this.center.length) {
          const center = this.data?.[0]?.lnglats || []
          if (center.length) {
            param.center = center
          }
        }
        if (this.center.length) {
          param.center = this.center
        }

        this.map = new AMap.Map('markerContainer', param)
      
        this.$emit('onload', this)
        this.map.on('click', event => {
          console.log(event)
        })
      } catch (error) {
        console.log('Map Error', error)
      } finally {
        this.loading = false
      }
    },

    setMarker(data, type) {
      const dataSource = {
        type: 'FeatureCollection',
        features: []
      };
      for (let item of data) {
        dataSource.features.push({
          type: 'Feature',
          properties: item,
          geometry: {
            type: 'Point',
            coordinates: [
              parseFloat(item.longitude),
              parseFloat(item.latitude)
            ]
          }
        })
      }
      if (this.mapLoca) {
        this.mapLoca.clear()
      } else {
        this.mapLoca = new Loca.Container({ map: this.map })
      }
      const breathScatter = new Loca.ScatterLayer({
        zIndex: 112,
        opacity: 1,
        visible: true,
        zooms: [2, 24],
      })

      breathScatter.setSource(new Loca.GeoJSONSource({ data: dataSource }))
      breathScatter.setStyle({
        unit: 'meter',
        zIndex: 112,
        size: [1500, 1500],
        borderWidth: 0,
        texture: type === 1 ? MapRed : (type === 2 ? MapGreen : MapBlue),
        duration: 600,
        animate: true,
      });
      this.mapLoca.add(breathScatter)
      // 启动渲染动画
      this.mapLoca.animate.start()

      //this.removeMarker()
      this.removeClusterer()
      const markerList = []
      if (!data) {
        data = this.data
      }
      data.forEach((item) => {
        // if (typeof item.lnglats == 'undefined') {
        //   item.lnglats = [item.longitude, item.latitude]
        // }
        // const marker = new AMap.Marker({
        //   //map: this.map,
        //   zIndex: 100,
        //   content: this.getMakerContent(item.operation_category - 1, item.address),
        //   offset: new AMap.Pixel(12, -12),
        //   position: item.lnglats
        // })
        //
        // marker.content = this.getMarkerInfoWindowContent(item)
        // marker.on('click', this.markerClick)
        // markerList.push(marker)

        markerList.push({lnglat: [item.longitude, item.latitude], data: item})
      })

      //this.markerList = markerList
      // this.map.add(markerList)

      this.markerClusterer = new AMap.MarkerClusterer(this.map, markerList, {
        //gridSize: 30,
        clusterByZoomChange: true,
        maxZoom: 14,
        renderClusterMarker: (context) => {
          const item = context.clusterData[0].data
          context.marker.setContent(this.getMakerContent(item.operation_category - 1, item.address))
          context.marker.setOffset(new AMap.Pixel(12, -12))
          context.marker.content = this.getMarkerInfoWindowContent(item)
          context.marker.on('click', this.markerClick)
        },
        renderMarker: (context) => {
          const item = context.data[0].data
          context.marker.setContent(this.getMakerContent(item.operation_category - 1, item.address))
          context.marker.setOffset(new AMap.Pixel(12, -12))
          context.marker.content = this.getMarkerInfoWindowContent(item)
          context.marker.on('click', this.markerClick)
        }
      })
      // if (data.length) {
      //   this.map.setCenter([data[0].longitude, data[0].latitude])
      // } else {
      //   this.map.setCenter(this.center)
      // }
      // if (this.infoWindowIndex >= 0) {
      //   const target = this.markerList[this.infoWindowIndex]
      //   this.markerClick({target})
      // }


    },

    getMakerContent(iconIndex, text) {
      const colorMap = ['#f56c6c', '#17a68c', '#518fbc']
      return `<div style="color: ${colorMap[iconIndex]}; text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white; font-weight: 600; display: flex; width: 600px; overflow: hidden; height: 24px; line-height: 24px;">${text}</div>`
    },

    getMarkerInfoWindowContent(item) {
      const imgs = item.images
          .map((i) => `<img src="${i}" /> `)
          .join('')

      //let markerTagClass = ''
      const colorMap = ['#f56c6c', '#17a68c', '#518fbc']
      // if (item.operation_category === 1) {
      //   markerTagClass = 'danger'
      // } else if (!item.penalty) {
      //   markerTagClass = 'warning'
      // }
      //     <span class="${markerTagClass}">${item.operation_category_name} | ${item.penalty ? '已处罚' : '未处罚'}</span>
      const content = `<div class="marker">
                            <div class="marker-no" id="copy" data-val="${item.operation_no}">
                                ${item.operation_no} <i data-val="${item.operation_no}" class="el-icon-document-copy"></i>
                            </div>
                            <div class="marker-tag">
                              <span style="background: ${colorMap[item.operation_category-1]}">${item.operation_category_name} | ${item.penalty ? '已处罚' : '未处罚'}</span>
                            </div>
                            <div class="marker-li">
                              <span>异常说明:</span>${item.operation_category_name} ${item.exception_category_name}
                            </div>
                            <div class="marker-li">
                              <span>打标人:</span>${item.create_user} ${item.create_time}
                            </div>
                            <div class="marker-li">
                              <span>审核人:</span>${item.shenheName ? item.shenheName : ''}
                            </div>
                            <div class="marker-img">
                              ${imgs}
                            </div>
                          </div>`

      return content
    },

    getAddressByLnglat(lnglat) {
      return new Promise((resolve, reject) => {
        const geocoder = new AMap.Geocoder({
          radius: 100,
          extensions: 'all'
        })

        geocoder.getAddress(lnglat, (status, res) => {
          if (status === 'complete' && res.info === 'OK') {
            resolve(res.regeocode.addressComponent)
          } else {
            reject(new Error('Geocoding failed'))
          }
        })
      })
    },

    getLnglatByAddress(address) {
      return new Promise((resolve, reject) => {
        const geocoder = new AMap.Geocoder({
          radius: 100,
          extensions: 'all'
        })
        geocoder.getLocation(address, (status, res) => {
          if (status === 'complete' && res.info === 'OK') {
            let location = res.geocodes[res.geocodes.length - 1].location
            resolve([location.lng, location.lat])
          } else {
            reject(new Error('Geocoding failed'))
          }
        })
      })
    },

    async setCenterByAddress(address) {
      const lnglat = await this.getLnglatByAddress(address)
      this.map.setCenter(lnglat)
    },

    async getBoundariesByAddresses(addresses) {
      const districtSearch = new AMap.DistrictSearch({
        level: 'district',
        extensions: 'all',
        subdistrict: 0
      })
      let coordinates = []
      for (const address of addresses) {
        const coordinatesRes = await new Promise((resolve, reject) => {
          districtSearch.search(address, (status, result) => {
            if (status === 'complete' && result.info === 'OK') {
              let boundaries = []
              for (let i in result.districtList[0].boundaries[0]) {
                boundaries.push([
                  result.districtList[0].boundaries[0][i].lng,
                  result.districtList[0].boundaries[0][i].lat,
                ])
              }
              resolve(boundaries)
            } else {
              reject(new Error('Geocoding failed for address: ' + address))
            }
          })
        })
        coordinates.push(coordinatesRes)
      }
      return coordinates
    },

    async setHighlight(region, streets = [], zoom = 12, center = []) {
      this.map.getAllOverlays('polygon').forEach(overlay => {
        this.map.remove(overlay)
      })
      this.map.setZoom(zoom)
      if (center) {
        this.map.setCenter(center)
      }
      let coordinates
      if (typeof region[0] != 'object') {
        coordinates = await this.getBoundariesByAddresses(region)
      } else {
        coordinates = region
      }
     
      const outer = [
        new AMap.LngLat(-360, 90, true),
        new AMap.LngLat(-360, -90, true),
        new AMap.LngLat(360, -90, true),
        new AMap.LngLat(360, 90, true)
      ]
      this.map.add(new AMap.Polygon({
        path: [outer, ...coordinates],
        zIndex: 100,
        fillColor: '#000',
        strokeOpacity: 1,
        fillOpacity: 0.6,
        strokeColor: '#056090',
        strokeWeight: 3,
        strokeStyle: 'solid',
        strokeDasharray: [5, 5],
      }))
     

      if (streets && streets.length) {
        for (let i in streets) {
          this.map.add(new AMap.Polygon({
            path: [streets[i]],
            zIndex: 99,
            fillColor: '#2b8cbe',
            strokeOpacity: 1,
            fillOpacity: 0,
            strokeColor: '#2b8cbe',
            strokeWeight: 2,
            strokeStyle: 'dashed',
            strokeDasharray: [5, 5],
          }))
        }
      }

    },

    markerClick({target}) {
      if (target.content) {
        if (!this.infoWindow) {
          this.infoWindow = new AMap.InfoWindow({
            anchor: 'bottom-center',
            offset: new AMap.Pixel(0, -24)
          })
        }
        this.infoWindow.setContent(target.content)
        this.infoWindow.open(this.map, target.getPosition())
        this.copy()
        this.listenImageClick()
      } else {
        this.infoWindow.close(this.map)
      }
      this.$emit('markerClick', this.markerList.indexOf(target))
    },

    copy() {
      const copy = document.getElementById('copy')
      copy.addEventListener('click', ({target}) => {
        const text = target.dataset.val
        navigator.clipboard.writeText(text).then(() => {
          this.$message.success(`${text} 已复制`)
        })
      })
    },

    listenImageClick() {
      const dom = document.querySelector('.marker-img')
      const imgDom = dom.getElementsByTagName('img')
      const images = []
      for (const img of imgDom) {
        images.push(img.getAttribute('src'))
      }
      for (let i in imgDom) {
        if (imgDom[i].addEventListener) {
          imgDom[i].addEventListener('click', () => {
            this.$viewerApi({images: images, options: {initialViewIndex: i}})
          })
        }
      }
    },

    removeClusterer() {
      if (this.markerClusterer) {
        this.markerClusterer.setMap(null)
      }
      if (this.infoWindow) {
        this.infoWindow.close(this.map)
      }
    },

    removeMarker() {
      if (this.markerList?.length) {
        this.map.remove(this.markerList)
      }
      if (this.infoWindow) {
        this.infoWindow.close(this.map)
      }
    },

    addUav(id, position) {
     const marker = new AMap.Marker({
        map: this.map,
        position: position,
        zIndex: 999,
        icon: new AMap.Icon({
          size: new AMap.Size(36, 36),
          imageSize: new AMap.Size(36, 36),
          image: UavImage
        }),
        offset: new AMap.Pixel(-13, -26),
      })
      const passedPolyline = new AMap.Polyline({
        map: this.map,
        strokeColor: "#AF5",  //线颜色
        strokeWeight: 6,      //线宽
      });
      marker.on('click', () => {
        this.$emit('uavClick', id)
      })
      marker.on('moving', e => {
        passedPolyline.setPath(e.passedPath)
      })
      this.uav[id] = marker
      this.uavPassed[id] = passedPolyline
    },
    moveUav(id, position) {
      if (typeof this.uav[id] === 'undefined') {
        return this.addUav(id, position)
      }
      this.uav[id].moveTo(position, {
        duration: 1000,
        delay: 500,
      })
    },
    removeUav(id) {
      this.map.remove(this.uav[id])
      delete this.uav[id]
    }
  }
}
</script>

<style>
.amap-icon img {
  position: unset;
}
</style>

<style lang="scss" scoped>
#markerContainer {
  overflow: hidden;
  width: 100%;
  height: 700px;
  margin: 0;
}

::v-deep .amap-info-content {
  background: #0c243a;
  border-radius: 5px;
  padding: 10px !important;
}

::v-deep .bottom-center .amap-info-sharp {
  border-top: 8px solid #0c243a;
}

::v-deep .marker {
  min-width: 300px;
  color: #ccc;
  font-size: 13px;
  position: relative;

  > div {
    padding: 5px 0;
    letter-spacing: 1px;
  }

  &-close {
    position: absolute;
    right: 10px;
    top: 10px;
    cursor: pointer;
  }

  &-no {
    color: #518fbc;
    font-weight: bold;
  }

  &-tag {
    margin-left: 10px;

    .danger {
      background: #f56c6c !important;
    }

    .warning {
      background: #e6a23c !important;
    }

    span {
      background: #67c23a;
      color: #fff;
      font-size: 12px;
      border-radius: 2px;
      padding: 2px 4px;
    }
  }

  &-li {
    span {
      color: #518fbc;
      display: inline-block;
      width: 70px;
      text-align: right;
      margin-right: 10px;
    }
  }

  &-img {
    display: grid;
    grid-template-columns: 150px 150px;
    grid-template-rows: 100px 100px;
    grid-gap: 10px;

    div {
      position: relative;

      .zoom {
        position: absolute;
        bottom: 10px;
        right: 10px;
      }
    }

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      border-radius: 2px;
    }
  }

  .zoom,
  #copy {
    cursor: pointer;
  }
}
</style>
